home *** CD-ROM | disk | FTP | other *** search
- NAME msster
- ; File MSSTER.ASM
- include mssdef.h
- ; Copyright (C) 1985, 1993, Trustees of Columbia University in the
- ; City of New York. Permission is granted to any individual or institution
- ; to use this software as long as it is not sold for profit. This copyright
- ; notice must be retained. This software may not be included in commercial
- ; products without written permission of Columbia University.
- ;
- ; Edit history
- ; 27 August 1992 version 3.13
- ; 6 Sept 1991 version 3.11
- ; Last edit 22 Feb 1992
-
- public clscpt, defkey, clscpi, ploghnd, sloghnd, tloghnd
- public dopar, shokey, cptchr, pktcpt, targ, replay, repflg
- public kbdflg, shkadr, telnet, ttyact, write, dec2di, caplft
- public cnvlin, katoi, decout, valout, atoi, cnvstr
- public pntchr, pntflsh, pntchk, prnhand, prnopen
- public vfopen, vfread
-
- braceop equ 7bh ; opening curly brace
- bracecl equ 7dh ; closing curly brace
-
- data segment
- extrn flags:byte, trans:byte, diskio:byte, portval:word
- extrn rdbuf:byte, dosnum:word, filtst:byte, prnname:byte
- extrn comand:byte, kstatus:word, flowon:byte, flowoff:byte
-
- targ termarg <0,1,cptchr,0,parnon>
- crlf db cr,lf,'$'
- tmsg1 db cr,lf,'(Connecting to host, type $'
- tmsg3 db ' C to return to PC)',cr,lf,cr,lf,cr,lf,'$'
- erms21 db cr,lf,'?Cannot start the connection.$'
- erms25 db cr,lf,'?Input must be numeric$'
- erms22 db cr,lf,'?No open logging file$'
- erms23 db '*** Error writing session log, suspending capture ***$'
- erms24 db cr,lf,'?Error writing Packet log$'
- erms26 db ' *** PRINTER IS NOT READY *** press R to retry'
- db ' or D to discard printing: $'
- esctl db 'Control-$'
- repflg db 0 ; REPLAY or SET TERM REPLAY filespec flag
- rephlp db 'name of file to playback$'
- reperr db cr,lf,'?File not found$' ; for REPLAY command
- msgtxt db 'text to be written$'
-
- vfophlp db 'Filename$'
- vfopbad db cr,lf,'?Cannot open file $' ; filename follows
- vfclbad db cr,lf,'?Cannot close file$'
- vfoptwice db cr,lf,'?File is already open$'
- vfnofile db cr,lf,'?File is not open$'
- vfrbad db cr,lf,'?Error while reading file$'
- vfwbad db cr,lf,'?Error while writing file$'
- vfrdbad db cr,lf,'?more parameters are needed$'
- vfrdmsg db 'name of variable into which to read a line from file$'
- vfrhandle dw -1 ; READ FILE handle (-1 = invalid)
- vfwhandle dw -1 ; WRITE FILE handle
-
- opntab db 3 ; OPEN FILE table
- mkeyw 'Read',1
- mkeyw 'Write',2
- mkeyw 'Append',3
-
- inthlp db cr,lf,' ? This message F Dump screen to file'
- db cr,lf,' C Close the connection P Push to DOS'
- db cr,lf,' S Status of the connection Q Quit logging'
- db cr,lf,' M Toggle mode line R Resume logging'
- db cr,lf,' B Send a Break 0 Send a null'
- db cr,lf,' L Send a long 1.8 s Break H Hangup phone'
- db cr,lf,' A Send Telnet "Are You There" I Send Telnet'
- db ' "Interrupt Process"'
- db cr,lf,' Typing the escape character will send it to the host'
- db 0 ; this short-form obscures less screen area [jrd]
-
- intprm db 'Command> $'
- intclet db 'B','C','F','H','L' ; single letter commands
- db 'M','P','Q','R','S' ; must parallel dispatch table intcjmp
- db '?','0','A','I'
- numlet equ $ - intclet ; number of entries
- even
- intcjmp dw intchb,intchc,intchf,intchh,intchl
- dw intchm,intchp,intchq,intchr,intchs
- dw intchu,intchn,intayt,inttip
-
- prnhand dw 4 ; printer file handle (4 = DOS default)
-
- even
- ploghnd dw -1 ; packet logging handle
- sloghnd dw -1 ; session logging handle
- tloghnd dw -1 ; transaction logging handle
-
- clotab db 6
- mkeyw 'READ-FILE',4001h
- mkeyw 'WRITE-FILE',4002h
- mkeyw 'All-logs',logpkt+logses+logtrn
- mkeyw 'Packets',logpkt
- mkeyw 'Session',logses
- mkeyw 'Transaction',logtrn
-
- clseslog db cr,lf,' Closing Session log$'
- clpktlog db cr,lf,' Closing Packet log$'
- cltrnlog db cr,lf,' Closing Transaction log$'
- clohlp db cr,lf,' READ-FILE or WRITE-FILE, or the following log files:'
- db cr,lf,' All-logs, Packets, Session, Transaction$'
-
- writetab db 5 ; Write command log file types
- mkeyw 'FILE',4002h ; FILE
- mkeyw 'Packet',logpkt
- mkeyw 'Screen',80h ; unused value, to say screen
- mkeyw 'Session',logses
- mkeyw 'Transaction',logtrn
-
- sttmsg db cr,lf,'Press space to continue ...$'
- kbdflg db 0 ; non-zero means char here from Term
- ttyact db 0 ; Connect mode active, if non-zero
- shkadr dw 0 ; offset of replacement Show Key cmd
- nbase dw 10 ; currently active number base
- numset db '0123456789ABCDEF' ; number conversion alphabet
- temp dw 0
- tmp db 0
- pktlft dw cptsiz ; number free bytes left
- caplft dw cptsiz ; number free bytes left
- data ends
-
- data1 segment
- pktbuf db cptsiz dup (0) ; packet logging buffer
- pktbp dw pktbuf ; buffer pointer to next free byte
- capbuf db cptsiz dup (0) ; session logging buffer
- capbp dw capbuf ; buffer pointer to next free byte
- prnbuf db cptsiz dup (0) ; printer buffer
- pntptr dw prnbuf ; pointer to next free byte
- data1 ends
-
- code segment
- extrn comnd:near, outchr:near, stat0:near, iseof:near
- extrn term:near, strlen:near, pcwait:near, isfile:near
- extrn beep:near, puthlp:near, serhng:near
- extrn serini:near, serrst:near, sendbr:near, putmod:near
- extrn fpush:near, dumpscr:near, sendbl:near, prtasz:near
- extrn trnmod:near, dodecom:near
- assume cs:code, ds:data, es:nothing
-
- ; the show key command
- shokey proc near
- cmp shkadr,0 ; keyboard translator present?
- je shokey1 ; e = no, use regular routines
- mov bx,shkadr ; get offset of replacement routine
- jmp bx ; and execute it rather than us
- shokey1:clc
- ret
- shokey endp
- ; enter with ax/scan code to define, si/ pointer to definition, cx/ length
- ; of definition. Defines it in definition table. Obsolete.
- defkey proc near
- ret
- defkey endp
-
- ; This is the CONNECT command
-
- TELNET PROC NEAR
- mov ah,cmeol
- call comnd ; get a confirm
- jnc teln1 ; nc = success
- ret
- teln1: call serini ; ensure port is inited now
- jnc teln1a ; nc = success
- test flags.remflg,dquiet ; quiet display mode?
- jnz teln1b ; nz = yes. Don't write to screen
- mov dx,offset erms21 ; say cannot start connection
- mov ah,prstr
- int dos
- teln1b: or kstatus,ksgen ; general command failure
- ret
- teln1a: cmp flags.vtflg,0 ; emulating a terminal?
- jne teln2 ; ne= yes, no wait necessary
- mov ah,prstr
- mov dx,offset crlf ; output a crlf
- int dos
- call domsg ; reassure user
- mov ax,2000 ; two seconds
- call pcwait ; pause
- teln2: xor al,al ; initial flags
- mov ttyact,1 ; say telnet is active
- cmp flags.vtflg,0 ; emulating a terminal?
- je teln3 ; e = no, say mode line is to be off
- cmp flags.modflg,0 ; mode line enabled?
- jne tel010 ; ne = yes
- teln3: or al,modoff ; no, make sure it stays off
-
- tel010: test flags.debug,logses ; debug mode?
- jz tel0 ; z = no, keep going
- or al,trnctl ; yes, show control chars
- tel0: cmp flags.vtflg,0 ; emulating a terminal?
- je tel1 ; e = no
- or al,emheath ; say emulating some kind of terminal
- tel1: mov bx,portval
- cmp [bx].ecoflg,0 ; echoing?
- jz tel2 ; z = no
- or al,lclecho ; turn on local echo
- tel2: mov targ.flgs,al ; store flags
- mov ah,flags.comflg ; COMs port identifier
- mov targ.prt,ah ; Port 1 or 2, etc
- mov ah,[bx].parflg ; parity flag
- mov targ.parity,ah
- mov ax,[bx].baud ; baud rate identifier
- mov targ.baudb,al
- xor ah,ah
- test flags.capflg,logses ; select session logging flag bit
- jz tel3 ; z = no logging
- mov ah,capt ; set capture flag
- tel3: or targ.flgs,ah
- jmp short tem1
-
- TEM: call serini ; init serial port
- jnc tem1 ; nc = success
- mov ttyact,0 ; say we are no longer active
- clc
- ret ; and exit Connect mode
-
- tem1: mov dx,offset crlf ; give user an indication that we are
- mov ah,prstr ; entering terminal mode
- int dos
- mov ax,offset targ ; point to terminal arguments
- call term ; call the main Terminal procedure
- mov al,kbdflg ; get the char from Term, if any
- mov kbdflg,0 ; clear the flag
- or al,al ; was there a char from Term?
- jnz intch2 ; nz = yes, else ask for one from kbd
-
- intchar:call iseof ; stdin at eof?
- jnc intch1 ; nc = not eof, get more
- mov al,'C' ; use C when file is empty
- jmp short intchc ; to provide an exit
- intch1: mov ah,0ch ; clear Bios keyboard buffer and do
- mov al,coninq ; read keyboard, no echo
- int dos ; get a char
- or al,al ; scan code indicator?
- jnz intch2 ; nz = no, ascii
- mov ah,coninq ; read and discard scan code
- int dos
- jmp short intch1 ; try again
- intch2: mov flags.cxzflg,0 ; prevent Control-C carryover
- cmp al,' ' ; space?
- je tem ; e = yes, ignore it
- cmp al,cr ; check ^M (cr) against plain ascii M
- je tem ; exit on cr
- cmp al,trans.escchr ; is it the escape char?
- jne intch3 ; ne = no
- mov ah,al
- call outchr
- jmp short tem ; return, we are done here
- intch3: push es
- push ds
- pop es
- mov di,offset intclet ; command letters
- mov cx,numlet ; quantity of them
- cmp al,' ' ; control code?
- jae intch3a ; ae = no
- or al,40H ; convert control chars to printable
- intch3a:cmp al,96 ; lower case?
- jb intch3b ; b = no
- and al,not (20h) ; move to upper case
- intch3b:cld
- repne scasb ; find the matching letter
- pop es
- jne intch4 ; ne = not found, beep and get another
- dec di ; back up to letter
- sub di,offset intclet ; get letter number
- shl di,1 ; make it a word index
- jmp intcjmp[di] ; dispatch to it
- intch4: call beep ; say illegal character
- jmp intchar
-
- intayt: mov ah,255 ; 'I' Telnet Are You There
- call outchr ; send IAC (255) AYT (246)
- mov ah,246
- call outchr
- jmp tem
-
- intchb: call sendbr ; 'B' send a break
- jmp tem ; And return
-
- intchc: mov ttyact,0 ; 'C' say we are no longer active
- clc ; and exit Connect mode
- ret
-
- intchf: call dumpscr ; 'F' dump screen, use msy routine
- jmp tem ; and return
-
- intchh: call serhng ; 'H' hangup phone
- call serrst ; turn off port
- jmp tem
-
- intchl: call sendbl ; 'L' send a long break
- jmp tem
-
- inttip: mov ah,255 ; 'I' Telnet Interrrupt Process
- call outchr ; send IAC (255) IP (244)
- mov ah,244
- call outchr
- jmp tem
-
- intchm: cmp flags.modflg,1 ; 'M' toggle mode line, enabled?
- jne intchma ; ne = no, leave it alone
- xor targ.flgs,modoff ; enabled, toggle its state
- intchma:jmp tem ; and reconnect
-
- intchp: call fpush ; 'P' push to DOS
- mov dx,offset sttmsg ; say we have returned
- mov ah,prstr
- int dos
- jmp short intchsb ; wait for a space
-
- intchq: and targ.flgs,not capt ; 'Q' suspend session logging
- jmp tem ; and resume
-
- intchr: test flags.capflg,logses ; 'R' resume logging. Can we capture?
- jz intchr1 ; z = no
- or targ.flgs,capt ; turn on session logging flag
- intchr1:jmp tem ; and resume
-
- intchs: call stat0 ; 'S' status, call stat0
- mov dx,offset sttmsg
- mov ah,prstr
- int dos
- intchsa:call iseof ; is stdin at eof?
- jnc intchsb ; nc = not eof, get more
- jmp tem ; resume if EOF
- intchsb:mov ah,coninq ; console input, no echo
- int dos
- cmp al,' ' ; space?
- jne intchsa
- jmp tem
-
- intchu: mov ax,offset inthlp ; '?' get help message
- call puthlp ; write help msg
- mov dx,offset intprm
- mov ah,prstr ; Print it
- int dos
- jmp intchar ; Get another char
-
- intchn: xor ah,ah ; '0' send a null
- call outchr
- jmp tem
- TELNET ENDP
-
- ; Reassure user about connection to the host. Tell him what escape sequence
- ; to use to return
-
- DOMSG PROC NEAR
- mov ah,prstr
- mov dx,offset tmsg1
- int dos
- call escprt
- mov ah,prstr
- mov dx,offset tmsg3
- int dos
- ret
- DOMSG ENDP
-
- ; print the escape character in readable format.
-
- ESCPRT PROC NEAR
- mov dl,trans.escchr
- cmp dl,' '
- jge escpr2
- push dx
- mov ah,prstr
- mov dx,offset esctl
- int dos
- pop dx
- add dl,040H ; Make it printable
- escpr2: mov ah,conout
- int dos
- ret
- ESCPRT ENDP
-
-
- ; Set parity for character in Register AL
-
- dopar: push bx
- mov bx,portval
- mov bl,[bx].parflg ; get parity flag byte
- cmp bl,parnon ; No parity?
- je parret ; Just return
- and al,07FH ; Strip parity. Same as Space parity
- cmp bl,parspc ; Space parity?
- je parret ; e = yes, then we are done here
- cmp bl,parevn ; Even parity?
- jne dopar0 ; ne = no
- or al,al
- jpe parret ; pe = even parity now
- xor al,080H ; Make it even parity
- jmp short parret
- dopar0: cmp bl,parmrk ; Mark parity?
- jne dopar1 ; ne = no
- or al,080H ; Turn on the parity bit
- jmp short parret
- dopar1: cmp bl,parodd ; Odd parity?
- or al,al
- jpo parret ; Already odd, leave it
- xor al,080H ; Make it odd parity
- parret: pop bx
- ret
-
- ; REPLAY filespec through terminal emulator
- replay proc near
- mov dx,offset rdbuf ; place for filename
- mov bx,offset rephlp ; help
- mov repflg,0 ; clear the replay active flag
- mov ah,cmword ; get filename
- call comnd
- jc replay2 ; c = failure
- mov ah,cmeol ; get an EOL confirm
- call comnd
- jc replay2 ; c = failure
- mov ah,open2 ; open file
- xor al,al ; open readonly
- cmp byte ptr dosnum+1,2 ; above DOS 2?
- jna replay1 ; na = no, so no shared access
- mov al,0+40h ; open readonly, deny none
- replay1:mov dx,offset rdbuf ; asciiz filename
- int dos
- jnc replay3 ; nc = success
- mov ah,prstr
- mov dx,offset reperr ; Cannot open that file
- int dos
- clc
- replay2:ret
- replay3:mov diskio.handle,ax ; file handle
- mov repflg,1 ; set replay flag
- call telnet ; enter Connect mode
- mov bx,diskio.handle
- mov ah,close2 ; close the file
- int dos
- mov repflg,0 ; clear the flag
- clc
- ret
- replay endp
-
- cptchr proc near ; session capture routine, char in al
- test flags.capflg,logses ; session logging active now?
- jz cptch1 ; z = no
- push di
- push es
- mov di,data1 ; seg of capbp and capbuf
- mov es,di
- cld
- mov di,es:capbp ; buffer pointer
- stosb
- inc es:capbp
- pop es
- pop di
- dec caplft ; decrement chars remaining
- jg cptch1 ; more room, forget this part
- call cptdmp ; dump the info
- cptch1: ret
- cptchr endp
-
- cptdmp proc near ; empty the capture buffer
- push ax
- push bx
- push cx
- push dx
- mov bx,sloghnd ; get file handle
- or bx,bx ; is file open?
- jle cptdm1 ; le = no, skip it
- mov cx,cptsiz ; original buffer size
- sub cx,caplft ; minus number remaining
- jl cptdm2 ; means error
- jcxz cptdm1 ; z = nothing to do
- push ds
- mov dx,data1 ; seg of capbuf
- mov ds,dx
- mov dx,offset capbuf ; the capture routine buffer
- mov ah,write2 ; write with filehandle
- int dos ; write out the block
- pop ds
- jc cptdm2 ; carry set means error
- cmp ax,cx ; wrote all?
- jne cptdm2 ; no, an error
- push es
- mov dx,data1 ; seg of capbuf and capbp
- mov es,dx
- mov es:capbp,offset capbuf
- pop es
- mov caplft,cptsiz ; init buffer ptr & chrs left
- clc
- jmp short cptdm1
- cptdm2: and targ.flgs,not capt ; so please stop capturing
- and flags.capflg,not logses ; deselect session logging flag bit
- mov dx,offset erms23 ; tell user the bad news
- call putmod ; write on mode line
- stc
- cptdm1: pop dx
- pop cx
- pop bx
- pop ax
- ret
- cptdmp endp
-
- pktcpt proc near ; packet log routine, char in al
- test flags.capflg,logpkt ; logging packets now?
- jz pktcp1 ; z = no
- push di
- push es
- mov di,data1 ; seg of pktbuf and pktbp
- mov es,di
- mov di,es:pktbp ; buffer pointer
- cld
- stosb ; store char in buffer
- inc es:pktbp ; move pointer to next free byte
- pop es
- pop di
- dec pktlft ; decrement chars remaining
- jg pktcp1 ; g = more room, forget this part
- call pktdmp ; dump the info
- pktcp1: ret
- pktcpt endp
-
- pktdmp proc near ; empty the capture buffer
- push ax
- push bx
- push cx
- push dx
- mov bx,ploghnd ; get file handle
- or bx,bx ; is file open?
- jle cptdm1 ; le = no, skip it
- mov cx,cptsiz ; original buffer size
- sub cx,pktlft ; minus number remaining
- jl pktdm2 ; l means error
- jcxz pktdm1 ; z = nothing to do
- push ds
- mov dx,data1 ; seg of pktbuf
- mov ds,dx
- mov dx,offset pktbuf ; the capture routine buffer
- mov ah,write2 ; write with filehandle
- int dos ; write out the block
- pop ds
- jc pktdm2 ; carry set means error
- cmp ax,cx ; wrote all?
- jne pktdm2 ; ne = no, error
- push es
- mov dx,data1 ; seg of pktbuf
- mov es,dx
- mov es:pktbp,offset pktbuf
- pop es
- mov pktlft,cptsiz ; init buffer ptr & chrs left
- jmp short pktdm1
- pktdm2: and flags.capflg,not logpkt ; so please stop capturing
- mov dx,offset erms24 ; tell user the bad news
- mov ah,prstr
- int dos
- call clscp4 ; close the packet log
- pktdm1: pop dx
- pop cx
- pop bx
- pop ax
- ret
- pktdmp endp
-
- ; CLOSE command
-
- clscpt proc near
- mov ah,cmkey ; get kind of file to close
- mov dx,offset clotab ; close table
- mov bx,offset clohlp ; help
- call comnd
- jc clscp2 ; c = failure
- mov temp,bx
- mov ah,cmeol
- call comnd
- jc clscp2 ; c = failure
- mov kstatus,kssuc ; success status thus far
- mov bx,temp
- cmp bh,40h ; READ-FILE or WRITE-FILE?
- jne clscp0 ; ne = no
- mov ax,bx
- jmp vfclose ; close FILE, pass kind in AX
- clscp0: cmp bx,logpkt+logses+logtrn ; close all?
- je clscpi ; e = yes
- cmp bx,logpkt ; just packet?
- je clscp4
- cmp bx,logses ; just session?
- je clscp6
- cmp bx,logtrn ; just session?
- jne clscp1 ; ne = no
- jmp clscp8
- clscp1: mov dx,offset erms22 ; say none active
- mov ah,prstr
- int dos
- clc
- ret
- clscp2: mov kstatus,ksgen ; general cmd failure status
- stc
- ret
- ; CLSCPI called at Kermit exit
- CLSCPI: mov bx,portval
- mov [bx].flowc,0 ; set no flow control so no sending it
- call pntflsh ; flush PRN buffer
- call clscp4 ; close packet log
- call clscp6 ; close session log
- call clscp8 ; close transaction log
- mov al,2 ; close WRITE FILE log
- call vfclose
- clc ; return success
- ret
-
- clscp4: push bx ; PACKET LOG
- mov bx,ploghnd ; packet log handle
- or bx,bx ; is it open?
- jle clscp5 ; e = no
- call pktdmp ; dump buffer
- mov ah,close2
- int dos
- cmp flags.takflg,0 ; ok to echo?
- je clscp5 ; e = no
- mov ah,prstr
- mov dx,offset clpktlog ; tell what we are doing
- int dos
- clscp5: mov ploghnd,-1 ; say handle is invalid
- pop bx
- and flags.capflg,not logpkt ; say this log is closed
- ret
-
- clscp6: push bx ; SESSION LOG
- mov bx,sloghnd ; session log handle
- or bx,bx ; is it open?
- jle clscp7 ; e = no
- call cptdmp ; dump buffer
- mov ah,close2
- int dos
- cmp flags.takflg,0 ; ok to echo?
- je clscp7 ; e = no
- mov ah,prstr
- mov dx,offset clseslog ; tell what we are doing
- int dos
- clscp7: mov sloghnd,-1 ; say handle is invalid
- pop bx
- and flags.capflg,not logses ; say this log is closed
- ret
-
- clscp8: push bx ; TRANSACTION LOG
- mov bx,tloghnd ; transaction log handle
- or bx,bx ; is it open?
- jle clscp9 ; e = no
- mov ah,close2
- int dos
- cmp flags.takflg,0 ; ok to echo?
- je clscp9 ; e = no
- mov ah,prstr
- mov dx,offset cltrnlog ; tell what we are doing
- int dos
- clscp9: mov tloghnd,-1 ; say handle is invalid
- pop bx
- and flags.capflg,not logtrn ; say this log is closed
- ret
- clscpt endp
-
- ; Print on PRN the char in register al. On success return with C bit clear.
- ; On failure do procedure pntchk and return its C bit (typically C set).
- ; Uses buffer dumpbuf (screen dump).
- pntchr proc near
- push es
- push ax
- mov ax,data1 ; segment of pntptr and prnbuf
- mov es,ax
- cmp es:pntptr,offset prnbuf+cptsiz ; buffer full yet?
- pop ax
- pop es
- jb pntchr1 ; b = no
- call pntflsh ; flush buffer now
- jnc pntchr1 ; nc = success
- ret ; c = fail, discard char
- pntchr1:push es
- push bx
- mov bx,data1 ; segment of pntptr and prnbuf
- mov es,bx
- mov bx,es:pntptr ; pointer to next open slot
- mov es:[bx],al ; store the character
- inc bx ; update pointer
- mov es:pntptr,bx ; save pointer
- pop bx
- pop es
- clc ; clear carry bit
- ret
- pntchr endp
-
- ; Flush printer buffer. Return carry clear if success.
- ; On failure do procedure pntchk and return its C bit (typically C set).
- ; Uses buffer dumpbuf (screen dump).
- pntflsh proc near
- push es
- push ax
- mov ax,data1 ; segment of pntptr and prnbuf
- mov es,ax
- cmp es:pntptr,offset prnbuf ; any text in buffer?
- pop ax
- pop es
- ja pntfls1 ; a = yes
- clc
- ret ; else nothing to do
- pntfls1:cmp prnhand,0 ; is printer handle valid?
- jg pntfls2 ; g = yes
- push es
- push ax
- mov ax,data1 ; segment of pntptr and prnbuf
- mov es,ax
- mov es:pntptr,offset prnbuf
- pop ax
- pop es
- clc ; omit printing, quietly
- ret
- pntfls2:push ax
- push bx
- push cx
- push dx
- push si
- push di
- push es
- mov ah,flowoff ; get flow control char
- or ah,ah ; flow control active?
- jz pntfls3 ; z = no, not using xoff
- call outchr ; output xoff (ah), no echo
- pntfls3:mov bx,prnhand ; file handle for DOS printer PRN
- push DS ; about to change DS
- mov dx,data1 ; segment of prnbuf
- mov ds,dx ; set DS
- mov dx,offset prnbuf ; start of buffer
- mov cx,ds:pntptr
- sub cx,dx ; cx = current byte count
- pntfls4:push cx
- push dx
- mov cx,1
- mov ah,write2
- int dos ; write buffer to printer
- pop dx
- pop cx
- jc pntfls5 ; c = call failed
- cmp ax,1 ; did we write it?
- jne pntfls5 ; ne = no, dos critical error
- inc dx ; point to next char
- loop pntfls4
- mov ds:pntptr,offset prnbuf ; reset buffer pointer
- pop DS ; restore DS
- clc ; declare success
- jmp pntfls11
- pntfls5:mov si,dx ; address of next char to be printed
- mov di,offset prnbuf ; start of buffer
- sub dx,di ; dx now = number successful prints
- mov cx,ds:pntptr
- sub cx,si ; count of chars to be printed
- jle pntfls6
- mov ax,ds
- mov es,ax
- cld
- rep movsb ; copy unwritten to start of buffer
- pntfls6:sub ds:pntptr,dx ; move back printer pointer by ok's
- pop DS ; restore DS
-
- pntfls7:mov dx,offset erms26 ; printer not ready, get user action
- call putmod ; write new mode line
- call beep ; make a noise
- mov ah,0ch ; clear DOS typeahead buffer
- mov al,1 ; read from DOS buffer
- int dos
- or al,al ; Special key?
- jnz pntfls8 ; nz = no, consume
- mov al,1 ; consume scan code
- int dos
- jmp short pntfls7 ; try again
-
- pntfls8:and al,not 20h ; lower to upper case quickie
- cmp al,'R' ; Retry?
- jne pntfls8a ; ne = no
- call trnmod ; toggle mode line
- call trnmod ; back to same state as before
- jmp pntfls3 ; go retry
- pntfls8a:cmp al,'D' ; Discard printing?
- jne pntfls7 ; ne = no, try again
- mov bx,prnhand
- cmp bx,4 ; stdin/stdout/stderr/stdaux/stdprn?
- jbe pntfls9 ; be = yes, always available
- mov ah,close2 ; close this file
- int dos
- pntfls9:mov bx,offset prnname ; name of printer file
- mov word ptr [bx],'UN' ; set to NUL<0>
- mov word ptr [bx+2],'L'+0
- push es
- mov ax,data1 ; seg for pntptr
- mov es,ax
- mov es:pntptr,offset prnbuf ; reset pointer
- pop es
- mov prnhand,-1 ; declare handle invalid
- pntfls10:call trnmod ; toggle mode line
- call trnmod ; back to same state as before
- stc ; declare failure
- pntfls11:pushf
- mov ah,flowon
- or ah,ah ; flow control active?
- jz pntfls12 ; z = no, not using xon
- call outchr ; output xon (al), no echo
- pntfls12:popf
- pop es
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- ret ; nc = success
- pntflsh endp
-
- ; Check for PRN (DOS's printer) being ready. If ready, return with C clear
- ; Otherwise, write Not Ready msg on mode line and return with C bit set.
- ; N.B. DOS Critical Error will occur here if PRN is not ready. [jrd]
- pntchk proc near
- push dx
- push cx
- push ax
- mov cx,10 ; ten retries before declaring error
- cmp prnhand,0 ; printer handle valid?
- jle pntchk2 ; le = no, invalid
- pntchk0:push bx
- mov bx,prnhand ; file handle
- mov ah,ioctl ; get printer status, via DOS
- mov al,7 ; status for output
- int dos
- pop bx
- jc pntchk1 ; c = call failed
- cmp al,0ffh ; code for Ready?
- je pntchk3 ; e = yes, assume printer is ready
- pntchk1:push cx ; save counter, just in case
- mov ax,100 ; wait 100 millisec
- call pcwait
- pop cx
- loop pntchk0 ; and try a few more times
- ; get here when printer is not ready
- pntchk2:pop ax
- pop cx
- pop dx
- stc ; say printer not ready
- ret
- pntchk3:pop ax
- pop cx
- pop dx
- clc ; say printer is ready
- ret
- pntchk endp
-
-
- prnopen proc near
- push ax
- push bx
- push cx
- push dx
- mov prnhand,4 ; preset default handle
- mov dx,offset prnname ; name of disk file, from mssset
- mov ax,dx ; where isfile wants name ptr
- call isfile ; what kind of file is this?
- jc prnop3 ; c = no such file, create it
- test byte ptr filtst.dta+21,1fh ; file attributes, ok to write?
- jnz prnop2 ; nz = no
- mov al,1 ; writing
- mov ah,open2 ; open existing file
- int dos
- jc prnop2 ; c = failure
- mov prnhand,ax ; save file handle
- mov bx,ax ; handle for DOS
- mov ah,ioctl
- mov al,0 ; get info
- int dos
- or dl,20h ; turn on binary mode
- xor dh,dh
- mov ah,ioctl
- mov al,1 ; set info
- int dos
- mov cx,0ffffh ; setup file pointer
- mov dx,-1 ; and offset
- mov al,2 ; move to eof minus one byte
- mov ah,lseek ; seek the end
- int dos
- pop dx
- pop cx
- pop bx
- pop ax
- clc
- ret
- prnop2: stc
- ret
- prnop3: test filtst.fstat,80h ; access problem?
- jnz prnop2 ; nz = yes
- mov ah,creat2 ; file did not exist
- mov cx,20h ; attributes, archive bit
- int dos
- mov prnhand,ax ; save file handle
- pop dx
- pop cx
- pop bx
- pop ax
- ret ; may have carry set
- prnopen endp
-
- ; worker: copy line from si to di, first removing trailing spaces, second
- ; parsing out curly braced strings, then third converting \{b##} in strings
- ; to binary numbers. Returns carry set if error; else carry clear, with byte
- ; count in cx. Braces are optional but must occur in pairs.
- ; Items which cannot be converted to legal numbers are copied verbatium
- ; to the output string (ex: \{c} is copied as \{c} but \{x0d} is hex 0dh).
- cnvlin proc near
- push ax
- push si ; source ptr
- push di ; destination ptr
- push es ; end of save regs
- push ds ; move ds into es
- pop es ; use data segment for es:di
- call cnvstr ; trim trailing, parse curly braces
- xor cx,cx ; initialize returned byte count
- cnvln1: cmp byte ptr [si],0 ; at end of string?
- je cnvln2 ; e = yes, exit
- call katoi ; read char, convert ascii to binary
- cld
- stosb ; save the char
- inc cx ; and count it
- or ah,ah ; is returned number > 255?
- jz cnvln1 ; z = no, do more chars
- push ax
- stosb ; save high order byte next
- pop ax
- inc cx
- jmp short cnvln1 ; do more chars
- cnvln2: mov byte ptr [di],0 ; plant terminator
- clc ; clear c bit, success
- pop es ; restore regs
- pop di ; destination ptr
- pop si ; source ptr
- pop ax
- ret
- cnvlin endp
-
- ; Convert string by first remove trailing spaces and then removing surrounding
- ; curly brace delimiter pair. Converts text in place.
- ; Enter with source ptr in si.
- ; Preserves all registers, uses byte tmp. 9 Oct 1987 [jrd]
- ;
- cnvstr proc near
- push ax
- push cx
- push dx
- push si ; save start of source string
- push di
- push es
- ; 1. Trim trailing spaces
- mov dx,si ; source address
- call strlen ; get current length to cx
- jcxz cnvst4 ; z = nothing there
- mov di,si ; set di to source address
- add di,cx ; start at end of string
- dec di ; ignore terminator
- mov al,spc ; scan while spaces
- push ds
- pop es ; set es to data segment
- std ; search backward
- repe scasb ; scan off trailing spaces
- mov byte ptr [di+2],0 ; terminate string after last text
- cld
- mov di,si ; set destination address to source
- ; 2. Parse off curly brace delimiters
- cmp byte ptr [si],braceop ; opening brace?
- jne cnvst4 ; ne = no, ignore brace-matching code
- inc si ; skip opening brace
- mov dl,braceop ; opening brace (we count them up)
- mov dh,bracecl ; closing brace (we count them down)
- mov tmp,1 ; we are at brace level 1
- cnvst1: cld ; search forward
- lodsb ; read a string char
- stosb ; store char (skips opening brace)
- or al,al ; at end of string?
- jz cnvst4 ; z = yes, we are done
- cmp al,dl ; an opening brace?
- jne cnvst2 ; ne = no
- inc tmp ; yes, increment brace level
- jmp short cnvst1 ; and continue scanning
-
- cnvst2: cmp al,dh ; closing brace?
- jne cnvst1 ; ne = no, continue scanning
- dec tmp ; yes, decrement brace level
- cmp byte ptr [si],0 ; have we just read the last char?
- jne cnvst3 ; no, continue scanning
- mov tmp,0 ; yes, this is the closing brace
- cnvst3: cmp tmp,0 ; at level 0?
- jne cnvst1 ; ne = no, #opening > #closing braces
- mov byte ptr [di-1],0 ; plant terminator on closing brace
-
- cnvst4: pop es ; recover original registers
- pop di
- pop si
- pop dx
- pop cx
- pop ax
- ret
- cnvstr endp
-
- ; Convert ascii strings of the form "\{bnnn}" to a binary word in ax.
- ; The braces are optional but must occur in pairs. Numeric base indicator "b"
- ; is O or o or X or x or D or d or missing, for octal, hex, or decimal (def).
- ; Enter with si pointing at "\".
- ; Returns binary value in ax with carry clear and si to right of "}" or at
- ; terminating non-numeric char if successful; otherwise, a failure,
- ; return carry set with si = entry value + 1 and first read char in al.
-
- katoi proc near
- cld
- lodsb ; get first char
- xor ah,ah ; clear high order field
- push cx ; save working reg
- push si ; save entry si+1
- push bx
- push ax ; save read char
- or al,al ; end of text?
- jz katoi1a ; z = yes, exit failure
- cmp al,'\' ; escape char?
- je katoi1b ; e = yes
- katoi1a:jmp katoix ; common jump point to exit failure
- katoi1b:lodsb ; get next char, maybe brace
- or al,al ; premature end?
- jz katoi1a ; z = yes, exit failure
- xor bx,bx ; no conv yet, assume no opening brace
- cmp al,braceop ; opening brace?
- jne katoi2 ; ne = no, have number or base
- mov bl,bracecl ; remember a closing brace is needed
- lodsb ; get number base, if any
- katoi2: xor cx,cx ; temporary place for binary value
- mov nbase,10 ; assume decimal numbers
- or al,al ; premature end?
- jz katoix ; z = yes, exit failure
- cmp al,'a' ; lower case?
- jb katoi3 ; b = no
- cmp al,'z' ; in range of lower case?
- ja katoi3 ; a = no
- and al,5fh ; map to upper case
- katoi3: cmp al,'O' ; octal?
- jne katoi4 ; ne = no
- mov nbase,8 ; set number base
- jmp short katoi6
- katoi4: cmp al,'X' ; hex?
- jne katoi5 ; ne = no
- mov nbase,16
- jmp short katoi6
- katoi5: cmp al,'D' ; decimal?
- jne katoi7 ; ne = no base char, assume decimal
- mov nbase,10
- katoi6: lodsb ; get a digit
- katoi7: or al,al ; premature end?
- jz katoi8a ; z = yes, use it as a normal end
- cmp al,bl ; closing brace?
- je katoi9 ; e = yes
- call cnvdig ; convert ascii to binary digit
- jc katoi8 ; c = cannot convert
- inc bh ; say we did a successful conversion
- xor ah,ah ; clear high order value
- push ax ; save this byte's value
- xchg ax,cx ; put binary summation in ax
- mul nbase ; scale up current sum
- xchg ax,cx ; put binary back in cx
- pop ax ; recover binary digit
- add cx,ax ; form running sum
- jc katoix ; c = overflow error, exit
- or dx,dx ; overflow?
- jnz katoix ; nz = yes, exit with error
- jmp short katoi6 ; get more
-
- katoi8: or bl,bl ; closing brace needed?
- jnz katoix ; nz = yes, but not found
- katoi8a:dec si ; backup to reread terminator
- katoi9: or bh,bh ; did we do any conversion?
- jz katoix ; z = no, exit failure
- pop ax ; throw away old saved ax
- pop bx ; restore bx
- pop ax ; throw away starting si, keep current
- mov ax,cx ; return final value in ax
- pop cx ; restore old cx
- clc ; clear carry for success
- ret
- katoix: pop ax ; restore first read al
- pop bx
- pop si ; restore start value + 1
- pop cx ; restore old cx
- stc ; set carry for failure
- ret
- katoi endp
-
- cnvdig proc near ; convert ascii code in al to binary
- push cx ; return carry set if cannot
- push es ; nbase has numeric base
- push di
- push ax
- cmp al,'a' ; lower case?
- jb cnvdig1 ; b = no
- cmp al,'f' ; highest hex digit
- ja cnvdigx ; a = illegal symbol
- sub al,'a'-'A' ; convert 'a' to 'f' to upper case
- cnvdig1:mov di,offset numset ; set of legal number symbols
- mov cx,nbase ; number of legal symbols in this base
- cmp cx,cx ; preset z flag
- push ds
- pop es ; point es at data segment
- cld ; scan forward
- repne scasb ; find character in set
- jne cnvdigx ; ne = not found
- inc cx ; offset auto-dec of repne scasb above
- sub cx,nbase ; counted off minus length
- neg cx ; two's complement = final value
- pop ax ; saved ax
- mov ax,cx ; return binary in al
- clc ; c clear for success
- jmp short cnvdixx ; exit
- cnvdigx:stc ; c set for failure
- pop ax
- cnvdixx:pop di
- pop es
- pop cx
- ret
- cnvdig endp
-
- decout proc near ; display decimal number in ax
- push ax
- push cx
- push dx
- mov cx,10 ; set the numeric base
- call valout ; convert and output value
- pop dx
- pop cx
- pop ax
- ret
- decout endp
-
- valout proc near ; output number in ax using base in cx
- ; corrupts ax and dx
- xor dx,dx ; clear high word of numerator
- div cx ; (ax / cx), remainder = dx, quotient = ax
- push dx ; save remainder for outputting later
- or ax,ax ; any quotient left?
- jz valout1 ; z = no
- call valout ; yes, recurse
- valout1:pop dx ; get remainder
- add dl,'0' ; make digit printable
- cmp dl,'9' ; above 9?
- jbe valout2 ; be = no
- add dl,'A'-1-'9' ; use 'A'--'F' for values above 9
- valout2:mov ah,conout
- int dos
- ret
- valout endp
-
- ; Convert input in buffer pointed to by SI to real number which is returned
- ; in DX:AX. Enter with string size in AH.
- ; Return carry set on failure, carry clear on success.
- ATOI PROC NEAR
- xor bx,bx ; high order of this stays 0
- mov tmp,bl ; no input yet
- mov cl,ah ; number of chars of input
- xor ch,ch ; size of string
- xor ax,ax ; init sum
- xor dx,dx ; high order part of sum
- cld
- atoi0: jcxz atoi4 ; Fail on no input
- mov bl,[si] ; get an input char
- inc si
- dec cx ; count number remaining
- cmp bl,' ' ; leading space?
- je atoi0 ; e = yes, skip it
- cmp bl,',' ; comma separator?
- je atoi0 ; e = yes, skip it
- dec si ; back up source pointer for reread below
- inc cx ; and readjust byte counter
- atoi1: mov bl,[si] ; get a new char
- inc si
- cmp bl,'9' ; check range for '0' to '9'
- ja atoi2 ; above '9'
- cmp bl,'0'
- jb atoi2 ; below '0'
- sub bl,'0' ; take away ascii bias
- push bx ; save digit and high null
- shl ax,1
- rcl dx,1 ; current sum * 2
- push dx
- push ax ; save it
- shl ax,1
- rcl dx,1
- shl ax,1
- rcl dx,1 ; times * 4 more
- pop bx ; low * 2
- add bx,ax
- mov ax,bx ; low order * 10
- pop bx
- adc bx,dx
- mov dx,bx ; high order * 10
- pop bx ; new digit and high null
- add ax,bx ; plus new digit
- adc dx,0
- mov tmp,1 ; say have sum being computed
- loop atoi1
- inc si ; inc for dec below
- atoi2: dec si ; point at terminator
- cmp tmp,0 ; were any digits discovered?
- je atoi4 ; e = no, fail
- clc ; success
- ret
- atoi4: mov dx,offset erms25 ; Input must be numeric
- stc ; failure
- ret
- ATOI ENDP
-
- ; Write binary number in AX as decimal asciiz to buffer pointer DI.
- dec2di proc near ; output number in ax using base in cx
- push ax
- push cx
- push dx
- mov cx,10
- call dec2di1 ; recursive worker
- pop dx
- pop cx
- pop ax
- ret
-
- dec2di1:xor dx,dx ; clear high word of numerator
- div cx ; (ax / cx), remainder = dx, quotient = ax
- push dx ; save remainder for outputting later
- or ax,ax ; any quotient left?
- jz dec2di2 ; z = no
- call dec2di1 ; yes, recurse
- dec2di2:pop dx ; get remainder
- add dl,'0' ; make digit printable
- mov [di],dl ; store char in buffer
- inc di
- mov byte ptr[di],0 ; add terminator
- ret
- dec2di endp
-
-
- ; OPEN { READ | WRITE | APPEND } filespec
- vfopen proc near
- mov ah,cmkey ; get READ/WRITE/APPEND keyword
- mov dx,offset opntab ; keyword table
- xor bx,bx ; help
- call comnd
- jc vfopen1 ; c = failed
- mov temp,bx
- mov ah,cmword ; read filespec
- mov dx,offset rdbuf ; buffer for filename
- mov bx,offset vfophlp ; help
- call comnd
- jc vfopen1 ; c = failed
- mov ah,cmeol ; get end of line confirmation
- call comnd
- jnc vfopen2
- mov kstatus,ksgen ; general cmd failure status
- vfopen1:ret ; error return, carry set
-
- vfopen2:mov kstatus,kssuc ; assume success status
- mov dx,offset rdbuf ; filename, asiiz
- mov bx,temp ; kind of open
- cmp bx,1 ; open for reading?
- jne vfopen4 ; ne = no
- ; OPEN READ
- cmp vfrhandle,0 ; is it open now?
- jge vfopen8 ; ge = yes, complain
- mov ah,open2 ; file open
- xor al,al ; 0 = open readonly
- cmp dosnum,300h ; at or above DOS 3?
- jb vfopen3 ; b = no, so no shared access
- or al,40h ; open readonly, deny none
- vfopen3:int dos
- jc vfopen9 ; c = failed to open the file
- mov vfrhandle,ax ; save file handle
- clc
- ret
- ; OPEN WRITE or APPEND
- vfopen4:cmp vfwhandle,0 ; is it open now?
- jge vfopen8 ; ge = yes, complain
- mov ax,dx ; filename for isfile
- call isfile ; check for read-only/system/vol-label/dir
- jc vfopen7 ; c = file does not exist
- test byte ptr filtst.dta+21,1fh ; the no-no file attributes
- jnz vfopen9 ; nz = do not write over one of these
- vfopen5:test filtst.fstat,80h ; access problem?
- jnz vfopen9 ; nz = yes, quit here
- test byte ptr filtst.dta+21,1bh ; r/o, hidden, volume label?
- jnz vfopen9 ; we won't touch these
- mov ah,open2 ; open existing file (usually a device)
- mov al,1+1 ; open for writing
- int dos
- jc vfopen9 ; carry set means can't open
- mov vfwhandle,ax ; remember file handle
- mov bx,ax ; file handle for lseek
- xor cx,cx
- xor dx,dx ; cx:dx = displacment
- xor al,al ; 0 means from start of file
- cmp temp,2 ; WRITE? means from start of file
- je vfopen6 ; e = yes, else APPEND
- mov al,2 ; move to eof
- vfopen6:mov ah,lseek ; seek the place
- int dos
- clc
- ret
-
- vfopen7:cmp temp,1 ; READ?
- je vfopen9 ; e = yes, should not be here
- mov ah,creat2 ; create file
- xor cx,cx ; 0 = attributes bits
- int dos
- jc vfopen9 ; c = failed
- mov vfwhandle,ax ; save file handle
- clc ; carry clear for success
- ret
-
- vfopen8:mov dx,offset vfoptwice ; trying to reopen a file
- mov ah,prstr
- int dos
- mov kstatus,kstake ; Take file failure status
- stc
- ret
- vfopen9:mov dx,offset vfopbad ; can't open, complain
- mov ah,prstr
- int dos
- mov dx,offset rdbuf ; filename
- call prtasz
- mov kstatus,kstake ; Take file failure status
- stc
- ret
- vfopen endp
-
- ; CLOSE {READ-FILE | WRITE-FILE}
- vfclose proc near
- mov tmp,al ; remember kind (1=READ, 2=WRITE)
- mov bx,vfrhandle ; READ FILE handle
- cmp al,1 ; READ-FILE?
- je vfclos1 ; e = yes
- cmp al,2 ; WRITE-FILE?
- jne vfclos3 ; ne = no, a mistake
- mov bx,vfwhandle ; write handle
- or bx,bx
- jl vfclos3 ; l = invalid handle
- mov dx,offset rdbuf
- xor cx,cx ; zero length
- push bx ; save handle
- mov ah,write2 ; set file high water mark
- int dos
- pop bx
- vfclos1:or bx,bx
- jl vfclos3 ; l = invalid handle
- mov kstatus,kssuc ; success status thus far
- mov ah,close2 ; close file
- int dos
- jc vfclos4 ; c = error
- cmp tmp,1 ; READ?
- jne vfclos2 ; ne = no, WRITE
- mov vfrhandle,-1 ; declare READ handle to be invalid
- clc
- ret
- vfclos2:mov vfwhandle,-1 ; declare WRITE handle to be invalid
- clc
- ret
- vfclos4:mov ah,prstr
- mov dx,offset vfclbad ; complain
- int dos
- vfclos3:mov kstatus,ksgen ; general cmd failure status
- stc
- ret
- vfclose endp
-
- ; READ-FILE variable name
- vfread proc near
- mov comand.cmper,1 ; do not react to '\%' in macro name
- mov ah,cmword
- mov dx,offset rdbuf+2 ; buffer for macro name
- mov word ptr rdbuf,0
- mov bx,offset vfrdmsg
- call comnd ; get macro name
- jnc vfread1 ; nc = success
- mov kstatus,ksgen ; general cmd failure status
- ret ; failure
- vfread1:or ax,ax ; null entry?
- jnz vfread2 ; nz = no
- mov dx,offset vfrdbad ; more parameters needed
- mov ah,prstr
- int dos
- mov kstatus,ksgen ; general cmd failure status
- stc
- ret
-
- vfread2:push ax
- mov ah,cmeol ; get command confirmation
- call comnd
- pop ax ; ax is variable length
- jc vfreadx ; c = failed
- mov cx,cmdblen ; length of rdbuf
- sub cx,ax ; minus macro name
- dec cx ; minus space separator
- mov temp,0 ; leading whitespace and comment flgs
- mov di,offset rdbuf+2 ; destination buffer
- add di,ax ; plus variable name
- mov byte ptr [di],' ' ; space separator
- inc di ; put definition here
- mov bx,vfrhandle ; READ FILE handle
- or bx,bx ; check for valid handle
- jge vfread3 ; ge = valid
- mov ah,prstr
- mov dx,offset vfnofile ; say no file
- int dos
- vfreadx:mov kstatus,ksgen ; general cmd failure status
- stc ; failure return
- ret
- vfread3:push cx ; read from file
- mov kstatus,kssuc ; assume success status
- mov cx,1 ; read 1 char
- mov dx,di ; place here
- mov byte ptr [di],0 ; insert terminator
- mov ah,readf2
- int dos
- pop cx
- jc vfreadx ; c = read failure
- or ax,ax ; count of bytes read
- jz vfread9 ; z means end of file
- mov al,[di] ; get the character
- cmp flags.takflg,0 ; echo Take files?
- je vfread3a ; e = no
- push ax
- mov ah,conout
- mov dl,al ; echo character
- int dos
- pop ax
- vfread3a:cmp al,CR ; CR?
- je vfread7 ; e = yes, ignore it
- cmp al,LF ; LF?
- je vfread8 ; e = yes, exit
- cmp al,';' ; start of comment?
- jne vfread4 ; ne = no
- mov byte ptr temp+1,1 ; say comment has started
- vfread4:cmp byte ptr temp+1,0 ; seen comment semicolon yet?
- jne vfread7 ; ne = yes, do not store comment
- cmp byte ptr temp,0 ; seen non-spacing char yet?
- jne vfread6 ; ne = yes
- cmp al,' ' ; is this a space?
- je vfread7 ; e = yes, skip it
- cmp al,TAB ; or a tab?
- je vfread7 ; e = yes, skip it
- mov byte ptr temp,1 ; say have seen non-spacing char
-
- vfread6:inc di ; next storage cell
- vfread7:loop vfread3 ; loop til end of line
-
- vfread8:cmp byte ptr [di-1],'-' ; last printable is line-continuation?
- jne vfread10 ; ne = no, use this line as-is
- dec di ; point to hyphen
- mov cx,offset rdbuf+cmdblen ; end of rdbuf
- sub cx,di ; minus where we are now
- jle vfread10 ; le = no space remaining
- mov temp,0 ; leading whitespace and comment flgs
- jmp vfread3 ; read another line
-
- vfread9:mov kstatus,ksgen ; EOF, general command failure status
-
- vfread10:cmp flags.takflg,0 ; echo Take files?
- je vfread11 ; e = no
- mov ah,prstr
- mov dx,offset crlf ; for last displayed line
- int dos
-
- vfread11:mov byte ptr [di],0 ; insert final terminator
- mov dx,offset rdbuf+2 ; start counting from here
- push kstatus ; preserve status from above work
- call strlen ; cx becomes length
- call dodecom ; create the variable
- pop kstatus ; recover reading status
- jc vfread12 ; c = failure
- ret
- vfread12:mov kstatus,ksgen ; general command failure status
- mov ah,prstr
- mov dx,offset vfrbad ; say error while reading
- int dos
- stc
- ret
- vfread endp
-
- ; WRITE {FILE or log} text
- Write proc near
- mov ah,cmkey ; get kind of log file
- mov dx,offset writetab ; table of possibilities
- xor bx,bx ; help, when we get there
- call comnd
- jnc write1 ; nc = success
- mov kstatus,ksgen ; general cmd failure status
- ret
- write1: mov temp,bx ; save log file kind
- mov ah,cmline ; get string to be written
- mov bx,offset rdbuf ; where to put text
- mov dx,offset msgtxt ; help
- call comnd
- mov ah,cmeol
- call comnd
- jnc wpkt0
- mov kstatus,ksgen ; general cmd failure status
- ret ; c = failure
- wpkt0: mov kstatus,kssuc ; success status thus far
- mov si,offset rdbuf ; start of text in buffer
- mov di,si ; convert in-place, to asciiz
- call cnvlin
- mov bx,temp ; log file kind
- mov si,offset rdbuf
- mov dx,si
- call strlen
- jcxz wpkt2 ; z = no chars to write
- cmp bx,logpkt ; Packet log?
- jne wses1 ; ne = no
- wpkt1: lodsb ; get byte to al
- call pktcpt ; write to packet log
- loop wpkt1
- wpkt2: clc ; say success
- ret
-
- wses1: cmp bx,logses ; Session log?
- jne wtrn1 ; ne = no
- wses2: lodsb ; get byte to al
- call cptchr ; write to log
- loop wses2 ; do cx chars
- clc ; say success
- ret
-
- wtrn1: cmp bx,logtrn ; Transaction log?
- jne wtrn2 ; ne = no
- mov bx,tloghnd ; file handle
- jmp short wtrn4
-
- wtrn2: cmp bx,80h ; WRITE SCREEN?
- jne wtrn3 ; ne = no
- xor bx,bx ; handle is stdout
- jmp short wtrn4
-
- wtrn3: cmp bx,4002h ; WRITE FILE?
- jne wtrn5 ; ne = no, forget this
- mov bx,vfwhandle ; handle
-
- wtrn4: or bx,bx ; is handle valid?
- jl wtrn5 ; l = no
- mov ah,write2 ; write to file handle in bx
- int dos
- jc wtrn4a ; c = failure
- ret
- wtrn4a: mov ah,prstr
- mov dx,offset vfwbad ; say error while writing
- int dos
- mov kstatus,ksgen
- stc
- ret
- wtrn5: mov kstatus,ksgen ; general cmd failure status
- mov ah,prstr
- mov dx,offset vfnofile ; say no file
- int dos
- stc
- ret
- write endp
- code ends
- end
-